import re

__PATTERN_NUMBER = r'^[+-]?\d+$'
__PATTERN_FLOAT = r'^[+-]?\d+(\.\d+)?$'


def has_abc(data: str):
    """
    判断字符串是否包含字母
    :param data:
    :return:
    """
    pattern = r'[a-zA-Z]+'
    result = re.search(pattern, data)
    return result is not None


def has_number(data: str):
    """
    判断字符串是否包含数字
    :param data:
    :return:
    """
    pattern = r'[0-9]+'
    result = re.search(pattern, data)
    return result is not None


def has_abc_or_number(data: str):
    """
    判断字符串是否包含字母、数字、字母+数字
    :param data:
    :return:
    """
    pattern = r'[a-zA-Z0-9]+'
    result = re.search(pattern, data)
    return result is not None


def has_special_char(data: str):
    """
    判断字符串中是否包含特殊字符
    :param data:
    :return:
    """
    pattern = r'[~!@#\$%\^&\*\(\)_\+\|`\-=\\\[\]\{\};\':",\./<>\?]'
    result = re.search(pattern, data, re.M)
    return result is not None


def is_abc_number_special_char(data: str):
    """
    判断字符串是否是 字母+数字+特殊字符
    常用于密码验证
    :param data:
    :return:
    """
    if not has_abc(data):
        return False
    if not has_number(data):
        return False
    if not has_special_char(data):
        return False
    pattern = r'^[a-zA-Z0-9~!@#\$%\^&\*\(\)_\+\|`\-=\\\[\]\{\};\':",\./<>\?]+$'
    result = re.search(pattern, data)
    return result is not None


def is_abc(data: str):
    """
    判断字符串是否是 字母
    :param data:
    :return:
    """
    pattern = r'^[a-zA-Z]+$'
    result = re.search(pattern, data)
    return result is not None


def is_number(data: str, symbol=False):
    """
    判断字符串是否是 数字
    :param data:
    :param symbol: 是否判断正负
    :return:
    """
    pattern = r'^[0-9]+$'
    if symbol:
        pattern = __PATTERN_NUMBER
    result = re.search(pattern, data)
    return result is not None


def is_abc_or_number(data: str):
    """
    判断字符串是否是 字母开头 + 字母、数字、字母
    常用于用户名判断
    :param data:
    :return:
    """
    pattern = r'^[a-zA-Z][a-zA-Z0-9]*$'
    result = re.match(pattern, data)
    return result is not None


def is_user_name(data: str):
    """
    判断字符串是否是用户名
    字母开头 + 字母、数字、字母、下划线
    :param data:
    :return:
    """

    pattern = r'^[a-zA-Z][a-zA-Z0-9_]*$'
    result = re.match(pattern, data)
    return result is not None


def is_email(data: str):
    """
    判断字符串是否是 邮箱地址
    :param data:
    :return:
    """
    pattern = r'^([A-Za-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$'
    result = re.match(pattern, data)
    return result is not None


def is_tel(data: str):
    """
    判断字符串是否是 电话号码
    :param data:
    :return:
    """
    pattern1 = r'^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$'
    pattern2 = r'^1[3456789]\d{9}$'
    result1 = re.match(pattern1, data)
    result2 = re.match(pattern2, data)
    return result1 is not None or result2 is not None


def is_bool(val):
    """
    是否是 bool 类型
    :param val:
    :return:
    """
    if val is None:
        return False
    if isinstance(val, bool):
        return True
    elif isinstance(val, str):
        return val.lower() in ('true', 'false', '1', '0')
    elif isinstance(val, int):
        return val in (1, 0)
    else:
        return False


def is_numeric(val):
    """
    判断是否是数字
    整数(正整数、负整数)、小数、单个简单数字表达示
    :param val:
    :return:
    """
    if isinstance(val, (int, float)):
        return True
    n = re.match(__PATTERN_NUMBER, val)
    f = re.match(__PATTERN_FLOAT, val)
    return n is not None or f is not None


def is_float(val):
    """
    是否是小数
    :param val: 字符串
    :return:
    """

    if isinstance(val, float):
        return True
    return re.match(__PATTERN_FLOAT, val) is not None